<?php
/**
 * Date: 2018/4/18
 * Time: 17:05
 * Author: zeronlee
 */

namespace App\Services\ChartAnalysis;

use App\Models\App;
use App\Models\Flaw\Level;
use App\Models\Flaw\Vuls;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use App\Services\ChartAnalysis\Data;

class Algorithm
{

    /**
     * 平均修复用时
     * @param int $level 不同级别（严重程度）
     * @param array $appIds 指定应用
     * @param array $time 指定时间
     * @return float $confirmAverageTime
     */
    public function confirmUsedTime ($level, $appIds, $time = []) {
        $confirmAverageTime = 0;
        $where = ['level_id' => $level,'status'=>Vuls::SOLVED];
        $queryBuilder = DB::table('vuls')->select([
            'id',
            'check_at'
        ])->where($where)->whereIn('app_id', $appIds);
        if (!is_null($time[0]) && !is_null($time[1])) {
            $queryBuilder->whereBetween('created_at', [
                Carbon::parse($time[0])->toDateTimeString(),
                Carbon::parse($time[1])->toDateTimeString()
            ]);
        }
        $vulsArr = $queryBuilder->get();
        $confirmTime = 0;
        $i = 0;
        foreach ($vulsArr as $item) {
            $closed_at = Carbon::parse(DB::table('vuls_record')
                ->where([['vuls_id','=',$item->id],['vuls_status','=',Vuls::CONFIRMED]])
                ->value('created_at'));
            if (is_null($closed_at)) {
                continue;
            }
            //已修复状态的时间减去审核时发邮件的时间
            if (!is_null($item->check_at)) {
                $check_at = Carbon::parse($item->check_at);
                $confirmTime += $closed_at->diffInMinutes($check_at) / 1440;
            } else {
                //审核时间
                $reviewTime = DB::table('vuls_record')->where([
                    'vuls_id' => $item->id,
                    'vuls_status' => Vuls::BECONFIRM
                ])->value('created_at');
                if (is_null($reviewTime)) {
                    continue;
                }
                $review_at = Carbon::parse($reviewTime);
                //没有邮件时间取审核时间
                $confirmTime += $closed_at->diffInMinutes($review_at) / 1440;
            }
            //统计个数
            $i++;
        }
        $confirmAverageTime = $i > 0 ? round($confirmTime / $i, 2) : 0;
        //测试日志
        \Log::info('等级id='.$level.'的漏洞数量是'.$i.'，平均用时：'.$confirmAverageTime);
        return $confirmAverageTime;
    }

    /**
     * 及时修复数量
     * @param int $level 不同级别（严重程度）
     * @param array $appIds 指定应用
     * @param array $time 指定时间
     * @return int
     */
    public function confirmTimelyNum ($level, $appIds, $time = []) {
        $num = 0;
        $builder = DB::table('vuls as v')->select([

                'l.term',
                'v.check_at',
                'v.id',
                'v.delayed_at'
            ])->leftJoin('level as l', 'l.id', '=', 'v.level_id')->whereIn('v.app_id', $appIds)->where(['l.id' => $level]);
        if (!is_null($time[0]) && !is_null($time[1])) {
            $builder->whereBetween('v.created_at', [
                Carbon::parse($time[0])->toDateTimeString(),
                Carbon::parse($time[1])->toDateTimeString()
            ]);
        }
        $info = $builder->get();
        foreach ($info as $item) {
            $closed_at = DB::table('vuls_record')
                ->where([['vuls_id','=',$item->id],['vuls_status','=',Vuls::CONFIRMED]])
                ->value('created_at');
            //审核时间
            $auditTime = DB::table('vuls_record')
                ->where([['vuls_id','=',$item->id],['vuls_status','=',Vuls::BECONFIRM]])
                ->value('created_at');
            //邮件时间为准，否则审核时间
            $created_at = !is_null($item->check_at) ? Carbon::parse($item->check_at ): Carbon::parse($auditTime);
            //修复时间在对应等级的时间范围内是及时完成
            //如果申请延期，在延期时间内也算及时
            if (!is_null($item->delayed_at) && $closed_at <= $item->delayed_at){
                $num++;
            }else{

                if ((!empty($closed_at) && !empty($created_at))&&
                    Carbon::parse($closed_at)->diffInDays($created_at) <= $item->term) {
                    $num++;
                }
            }
        }
        return $num;
    }

    /**
     * 综合统计
     * @param array $time
     * @return array $syn
     */
    public function staticSynthesized ($time) {
        $syn = [];
        $dataService = new Data();
        if (!is_null($time[0]) && !is_null($time[1])) {
            $syn['startTime'] = date('Y年m月d日', strtotime($time[0]));
            $syn['endTime']   = date('Y年m月d日', strtotime($time[1]));
            $dataService->timeVaild = true;
            $dataService->startime = $time[0];
            $dataService->endTime = $time[1];
        }
        else {
            $syn['startTime'] = '';
            $syn['endTime'] = '';
        }
        //init
        $dataService->getComposition(1);
        $appIds = $dataService->getAppIds();
        //应用数量
        if ($dataService->startime && $dataService->endTime){
            $syn['appsNum'] = Vuls::getCountBetweenTime($appIds,[Carbon::parse($dataService->startime),Carbon::parse($dataService->endTime)]);
        }else{
            $syn['appsNum'] = count($appIds);
        }
        //优化数据
        // $level = [Level::SERIOUSID,Level::HIGHRISKID,Level::INRISKID];
        // $synTemp =  $dataService->getFindNum($level);
        //严重漏洞个数
        $syn['total']  = $syn['seriousNum'] = $dataService->getFindNum([Level::SERIOUSID],0,$appIds);
        //高危漏洞个数
        $syn['total'] += $syn['secondNum'] = $dataService->getFindNum([Level::HIGHRISKID],0,$appIds);
        //其他漏洞个数
        $syn['total'] += $syn['otherNum'] = $dataService->getFindNum([Level::INRISKID],0,$appIds) + $dataService->getFindNum([Level::LOWID],0,$appIds) + $dataService->getFindNum([Level::NOEFFECT],0,$appIds);
        return $syn;
    }

}